package com.zmn.oms.business.impl.work;

import com.alibaba.fastjson.JSON;
import com.alibaba.nacos.shaded.org.checkerframework.checker.units.qual.A;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.zmn.base.plat.engine.common.util.response.DubboResponseUtils;
import com.zmn.base.engineer.common.constants.DubboConsts;
import com.zmn.base.engineer.dubbo.interfaces.engineer.certificate.EngineerCertificateListRemoteService;
import com.zmn.base.engineer.dubbo.interfaces.foreign.EngineerListRemoteService;
import com.zmn.common.constant.GlobalConsts;
import com.zmn.common.dto2.ResponseDTO;
import com.zmn.common.utils.collection.CollectionUtil;
import com.zmn.common.utils.date.DateUtil;
import com.zmn.common.utils.math.MoneyUtil;
import com.zmn.common.utils.number.NumberUtil;
import com.zmn.engstock.dubbo.interfaces.stock.StockListRemoteService;
import com.zmn.erp.dubbo.interfaces.newbiz.conf.ConfEngineerSubsidyRemoteListService;
import com.zmn.erp.dubbo.interfaces.newbiz.conf.ConfSpSubsidyRemoteListService;
import com.zmn.oms.business.interfaces.messageV1.app.MessageSendAppService;
import com.zmn.oms.business.interfaces.orderstock.OrderStockBService;
import com.zmn.oms.business.interfaces.performance.PerformanceUtilService;
import com.zmn.oms.business.interfaces.work.OrderWorkProgrammeBService;
import com.zmn.oms.business.interfaces.work.tag.OrderTagBService;
import com.zmn.oms.common.constant.*;
import com.zmn.oms.common.exception.OmsBaseException;
import com.zmn.oms.model.dto.orderstock.CheckLockStockDTO;
import com.zmn.oms.model.dto.orderstock.StockWhiteDTO;
import com.zmn.oms.model.dto.work.masterwork.WorkDetailDTO;
import com.zmn.oms.model.dto.work.masterwork.WorkListItemDTO;
import com.zmn.oms.model.dto.work.masterwork.WorkProgrammeDTO;
import com.zmn.oms.model.entity.changerecord.OrderChangeRecord;
import com.zmn.oms.model.entity.masterworking.MasterWorking;
import com.zmn.oms.model.entity.work.OrderWork;
import com.zmn.oms.services.interfaces.changerecord.OrderChangeRecordService;
import com.zmn.oms.services.interfaces.masterworking.MasterWorkingService;
import com.zmn.oms.services.interfaces.tag.OrderTagService;
import com.zmn.oms.services.interfaces.work.OrderWorkService;
import com.zmn.pay.common.constant.PayConsts;
import com.zmn.performance.common.constant.PerfConfConstant;
import com.zmn.performance.common.dio.conf.ConfEngineerBonusDIO;
import com.zmn.performance.common.dro.conf.five.BonusConfigFiveDRO;
import com.zmn.performance.common.dro.conf.five.ConfBonusFiveDRO;
import com.zmn.performance.common.dro.order.OrderTimeOutWarningCheckDRO;
import com.zmn.performance.common.enums.BizTypeEnum;
import com.zmn.performance.common.enums.OrderTimeoutTypeEnum;
import com.zmn.performance.common.enums.conf.timeout.ConfigName;
import com.zmn.performance.common.enums.conf.timeout.ConfigNodeType;
import com.zmn.performance.common.enums.conf.timeout.ConfigType;
import com.zmn.performance.dubbo.interfaces.conf.five.ConfEngineerFiveListRemoteService;
import com.zmn.performance.dubbo.interfaces.order.OrderTimeoutWarningListRemoteService;
import lombok.AllArgsConstructor;
import lombok.Data;
import org.apache.avro.data.Json;
import org.apache.commons.lang.BooleanUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.dubbo.config.annotation.Reference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.Duration;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author sunlife
 * @date:2021/3/12 6:02 下午
 * description:
 */
@Service
public class OrderWorkProgrammeBServiceImpl implements OrderWorkProgrammeBService {

    private Logger logger = LoggerFactory.getLogger(OrderWorkProgrammeBServiceImpl.class);

    private static final int OPERATE_STATUS_NORMAL = 1; // 正常
    private static final int OPERATE_STATUS_WARNING = 2; // 预警
    private static final int OPERATE_STATUS_TIMEOUT = 3; // 超时

    @Autowired
    OrderWorkService orderWorkService;
    @Autowired
    MessageSendAppService messageSendAppService;
    @Autowired
    OrderChangeRecordService orderChangeRecordService;
    @Autowired
    PerformanceUtilService performanceUtilService;
    @Autowired
    OrderStockBService orderStockBService;
    @Autowired
    MasterWorkingService masterWorkingService;
    @Autowired
    OrderTagBService orderTagBService;
    @Autowired
    OrderTagService orderTagService;

    @Reference(version = com.zmn.performance.dubbo.consts.DubboConsts.INTERFACE_VERSION, check = false)
    ConfEngineerFiveListRemoteService confEngineerFiveListRemoteService;
    @Reference(version = com.zmn.erp.dubbo.utils.DubboConsts.INTERFACE_VERSION, check = false)
    ConfEngineerSubsidyRemoteListService confEngineerSubsidyRemoteListService;
    @Reference(version = com.zmn.erp.dubbo.utils.DubboConsts.INTERFACE_VERSION, check = false)
    ConfSpSubsidyRemoteListService confSpSubsidyRemoteListService;
    @Reference(version = com.zmn.base.plat.engine.common.constant.DubboConsts.INTERFACE_VERSION, check = false)
    OrderTimeoutWarningListRemoteService orderTimeoutWarningListRemoteService;
    @Reference(version = DubboConsts.INTERFACE_VERSION, check = false)
    EngineerListRemoteService engineerListRemoteService;

    // @Reference(version = com.zmn.base.engineer.common.constants.DubboConsts.INTERFACE_VERSION, check = false)
    // BaseInfoListRemoteService baseInfoListRemoteService;

    @Reference(version = DubboConsts.INTERFACE_VERSION, check = false)
    EngineerCertificateListRemoteService engineerCertificateListRemoteService;

    @Reference(version = com.zmn.base.plat.engine.common.constant.DubboConsts.INTERFACE_VERSION, check = false)
    StockListRemoteService stockListRemoteService;
    private static final String TIP_NORMAL_TEMPLATE = "%s前%s,奖励%s元";
    private static final String TIP_NORMAL_SECTION_TEMPLATE = "%s间%s,奖励%s元";
    private static final String TIP_WARNING_TEMPLATE = "%s后%s超时";
    private static final String TIP_TIMEOUT_TEMPLATE = "%s已超时";
    private static final String DATE_TEMPLATE = "HH:mm";
    private static final String OPERATE_RESULT_SUCCESS_TEMPLATE_AMOUNT = "赞！准时%s，奖励：%s元，请继续保持哦~";
    private static final String OPERATE_RESULT_SUCCESS_TEMPLATE = "领单成功！您的工牌已发送用户。";
    private static final String OPERATE_RESULT_FAIL_TEMPLATE = "不清楚超时规则？点击：查看规则";
    private static final List<OrderTimeoutTypeEnum> TIMEOUT_LIST = Lists.newArrayList(OrderTimeoutTypeEnum.CONTACT, OrderTimeoutTypeEnum.DUTY, OrderTimeoutTypeEnum.VISIT);
    private static final List<OrderTimeoutTypeEnum> ZMN_CNHB_SHOW_LIST = Lists.newArrayList(OrderTimeoutTypeEnum.TAKE, OrderTimeoutTypeEnum.CONTACT, OrderTimeoutTypeEnum.VISIT, OrderTimeoutTypeEnum.COMPLETE);
    private static final List<OrderTimeoutTypeEnum> YEYX_SHOW_LIST = Lists.newArrayList(OrderTimeoutTypeEnum.DUTY, OrderTimeoutTypeEnum.VISIT, OrderTimeoutTypeEnum.COMPLETE);


    @Override
    public void processWorkDetailProgramList(List<WorkListItemDTO> dtos) throws OmsBaseException {
        if (CollectionUtil.isNullOrEmpty(dtos)) {
            return;
        }
        List<Long> orderIds = dtos.stream().map(WorkListItemDTO::getOrderId).collect(Collectors.toList());

        List<OrderWork> orderWorks = orderWorkService.listEsOrderWorkByOrderIdList(orderIds);

        Map<Long, OrderWork> orderWorkMap = orderWorks.stream().collect(Collectors.toMap(OrderWork::getWorkId, item -> item, (v1, v2) -> v1));

        List<DuplicateDTO> duplicateDTOS = orderWorks.stream().map(dto -> {
            return new DuplicateDTO(dto.getPlatWork(), dto.getManageCompanyId(), dto.getBizType());
        }).distinct().collect(Collectors.toList());

        // 获取配置
        Map<String, ConfBonusFiveDRO> confMap = Maps.newHashMap();

        for (DuplicateDTO duplicateDTO : duplicateDTOS) {
            logger.debug("获取绩效配置入参：platWork：{}, manageCompanyId：{}， bizType：{}", duplicateDTO.getPlatWork(), duplicateDTO.getManageCompanyId(), duplicateDTO.getBizType());
            ResponseDTO<ConfBonusFiveDRO> responseDTO = confEngineerFiveListRemoteService.getBonusOnlyPlusById(duplicateDTO.getPlatWork(), duplicateDTO.getManageCompanyId(), duplicateDTO.getBizType());
            logger.debug("获取绩效配置出参：{}", JSON.toJSONString(responseDTO));

            if (responseDTO.isSuccess() && Objects.nonNull(responseDTO.getData())) {
                String key = new StringBuilder().append(duplicateDTO.getPlatWork()).append(duplicateDTO.getManageCompanyId()).append(duplicateDTO.getBizType()).toString();
                confMap.put(key, responseDTO.getData());
            }
        }

        // 获取工单操作状态
        logger.debug("批量获取工单状态 入参：{}", JSON.toJSONString(orderIds));
        com.zmn.common.dto2.ResponseDTO<Set<OrderTimeOutWarningCheckDRO>> responseDTO = orderTimeoutWarningListRemoteService
                .checkOrderTimeoutWarning(Sets.newHashSet(orderIds));
        logger.debug("批量获取工单状态 出参：{}", JSON.toJSONString(responseDTO));

        Set<OrderTimeOutWarningCheckDRO> checkDROSet = Optional.ofNullable(responseDTO.getData()).orElse(Sets.newHashSet());

        Map<Long, OrderTimeOutWarningCheckDRO> checkDROMap = checkDROSet.stream().collect(Collectors.toMap(OrderTimeOutWarningCheckDRO::getOrderId, item -> item, (v1, v2) -> v1));

        // 直营 or 非直营  ResponseDTO<Integer> engineerByEngineerIdRsp =
        Integer masterId = orderWorks.get(0).getMasterId();
        logger.debug("processWorkDetailProgramList#getCertificatePassResult 入参 [{}]",masterId);
        ResponseDTO<Boolean> engineerByEngineerIdRsp = engineerCertificateListRemoteService.getCertificatePassResult(masterId);
        logger.debug("processWorkDetailProgramList#getCertificatePassResult 出参 [{}]",JSON.toJSONString(engineerByEngineerIdRsp));
        Boolean agent = Boolean.FALSE;
        if(engineerByEngineerIdRsp.isSuccess()){
            agent = engineerByEngineerIdRsp.getData();
        }

        // 处理工单日程信息
        for (WorkListItemDTO item : dtos) {
            OrderWork orderWork = orderWorkMap.get(item.getWorkId());
            if (Objects.isNull(orderWork)) {
                continue;
            }

            WorkProgrammeDTO programme = new WorkProgrammeDTO();

            // 处理多次上门操作名称
            if (NumberUtil.isNotNullOrZero(item.getMultipleVisitStatus())) {
                /*if (Objects.equals(item.getMultipleVisitStatus(), OrderVisitStatusConsts.ORDER_VISIT_STATUS_APPLY)
                        && Objects.equals(item.getMultiplePayStatus(), PayConsts.PAY_STATUS_DONE)) {
                    programme.setOperateStr("出发");
                    programme.setProgrammeStatus("已提交");
                    programme.setProgrammeStr("");
                    programme.setOperateTextStatus(AppConsts.OPERATE_TEXT_TYPE_VISIT_DEPART);
                    programme.setOperateText(AppConsts.getOperateText(AppConsts.OPERATE_TEXT_TYPE_VISIT_DEPART));
                    item.setProgramme(programme);
                    continue;
                } else */
                if ((Objects.equals(item.getMultipleVisitStatus(), OrderVisitStatusConsts.ORDER_VISIT_STATUS_APPLY)
                        && Objects.equals(item.getMultiplePayStatus(), PayConsts.PAY_STATUS_DONE))
                        || Objects.equals(item.getMultipleVisitStatus(), OrderVisitStatusConsts.ORDER_VISIT_STATUS_SET_OUT)) {
                    programme.setOperateStr("上门");
                    programme.setProgrammeStatus("已领单");
                    programme.setProgrammeStr("");
                    programme.setOperateTextStatus(AppConsts.OPERATE_TEXT_TYPE_VISIT_VISIT);
                    programme.setOperateText(AppConsts.getOperateText(AppConsts.OPERATE_TEXT_TYPE_VISIT_VISIT));
                    item.setProgramme(programme);
                    continue;
                }
            }

            programme.setOperateStatus(OPERATE_STATUS_NORMAL);
            OrderTimeOutWarningCheckDRO checkDRO = checkDROMap.get(item.getWorkId());
            if (Objects.nonNull(checkDRO)) {
                if (checkDRO.getHasTimeout()) {
                    programme.setOperateStatus(OPERATE_STATUS_TIMEOUT);
                } else if (checkDRO.getHasWarning()) {
                    programme.setOperateStatus(OPERATE_STATUS_WARNING);


                }
            }

            String key = String.valueOf(orderWork.getPlatWork()) + orderWork.getManageCompanyId() + orderWork.getBizType();
            ConfBonusFiveDRO conf = confMap.get(key);

            // 直营显示奖励信息
            if (agent && !Objects.equals(orderWork.getCompanyId(), CompanyConsts.ZMN_JXJ_COMPANY_ID) &&
                    (Objects.equals(orderWork.getPlatWork(), GlobalConsts.PLAT_MARK_ZMN) || Objects.equals(orderWork.getPlatWork(), GlobalConsts.PLAT_MARK_CNHB))
                    && !item.isExcludePerformance()) {
                // 处理进程奖励信息
                programme.setProgrammeStr(this.getWorkProgrammeInfo(orderWork, conf, programme.getOperateStatus()));
            } else {
                programme.setProgrammeStr("");
            }

            // 处理状态信息
            programme.setProgrammeStatus(this.getProgrammeStatus(orderWork));

            // 处理操作信息
            programme.setOperateStr(this.getOperateStr(orderWork));

            // 判断计划行程前后
            List<String> operateStrList = Arrays.asList("出发", "上门", "完成服务");
            final Integer planStroke = operateStrList.contains(programme.getOperateStr()) ? PlanStrokeConsts.PLAN_STROKE_AFTER : PlanStrokeConsts.PLAN_STROKE_BEFORE;
            programme.setPlanStroke(planStroke);
            // 改约改派
            this.getDistributeText(programme);
            // 处理操作信息
            Integer operateTextStatus = this.getOperateTextStatus(orderWork);
            programme.setOperateTextStatus(operateTextStatus);
            programme.setOperateText(AppConsts.getOperateText(operateTextStatus));
            // 处理超时时间 订单节点超时获取罚款金额
            this.getTimeOutDate(orderWork, programme);
            item.setProgramme(programme);
        }
    }

    /**
     * 改约改派
     *
     * @param programme 工单日程
     * @return
     */
    private void getDistributeText(WorkProgrammeDTO programme) {
        if (Objects.equals(programme.getOperateStatus(), OPERATE_STATUS_WARNING) && Objects.equals(programme.getProgrammeStatus(), "待上门")) {
            programme.setDistributeText("改约改派");
        }
    }

    /**
     * 计算超时时间
     *
     * @param orderWork 工单信息
     * @param programme 工单日程
     * @return
     */
    private void getTimeOutDate(OrderWork orderWork, WorkProgrammeDTO programme) {
        // 派单后计算领单超时时间
        final Date now = new Date();
        int minTime = 1;
        final Integer bizType = orderWork.getBizType();
        final Integer plat = orderWork.getPlat();
        final Integer manageCompanyId = orderWork.getManageCompanyId();
        ConfEngineerBonusDIO dio = new ConfEngineerBonusDIO();
        dio.setWorkId(orderWork.getWorkId());
        dio.setCompanyId(manageCompanyId);
        dio.setPlat(plat);
        dio.setBizType(bizType);
        final boolean distribute = Objects.equals(orderWork.getStatus(), OrderStatusConsts.WORK_STATUS_DISTRIBUTE) && Objects.equals(orderWork.getResultStatus(), OrderStatusConsts.WORK_RESULT_DOING);
        if (distribute) {
            final Integer distributeTineOutDate = Optional.ofNullable(DubboResponseUtils.resultToNull(() -> orderTimeoutWarningListRemoteService.getTimeoutWarningConfig(ConfigNodeType.TAKE, ConfigType.TIMEOUT, BizTypeEnum.codeOf(orderWork.getBizType()), ConfigName.OVER_DUTY_TIME))).orElse(0);
            final Date from = Date.from(orderWork.getDistributeTime().toInstant().plus(distributeTineOutDate, ChronoUnit.MINUTES));
            this.calculateTimeDiff(now,from);
            programme.setTimeOutDate(from.getTime());
            if (now.after(from)) {
                dio.setType(PerfConfConstant.INDEX_SHARE_TAKE);
                final long time = (now.getTime() - from.getTime()) / 1000 / 60;
                Integer amount = Math.abs(this.getBonusConfigFiveDRO(dio, false));
                programme.setTimeOutOperateText(NumberUtil.isNullOrZero(amount) ? "" : String.format("已领单超时%s分钟，处罚：%s元", time <= minTime ? 1 : time, MoneyUtil.parseToYuanStr(amount)));
            }
            return;
        }
        // 领单后计算联系用户超时时间
        final boolean contact = Objects.equals(orderWork.getStatus(), OrderStatusConsts.WORK_STATUS_TAKE) && Objects.isNull(orderWork.getContactTime()) && Objects.equals(orderWork.getResultStatus(), OrderStatusConsts.WORK_RESULT_DOING);
        if (contact) {

            final Integer contactTineOutDate = Optional.ofNullable(DubboResponseUtils.resultToNull(() -> orderTimeoutWarningListRemoteService.getTimeoutWarningConfig(ConfigNodeType.CONTACT, ConfigType.TIMEOUT, BizTypeEnum.codeOf(orderWork.getBizType()), ConfigName.OVER_DUTY_TIME))).orElse(0);
            final Date from = Date.from(orderWork.getTakeTime().toInstant().plus(contactTineOutDate, ChronoUnit.MINUTES));
            this.calculateTimeDiff(now,from);
            programme.setTimeOutDate(from.getTime());
            if (now.after(from)) {
                dio.setType(PerfConfConstant.INDEX_SHARE_CONTACT);
                final long time = (now.getTime() - from.getTime()) / 1000 / 60;
                Integer amount = Math.abs(this.getBonusConfigFiveDRO(dio, false));
                programme.setTimeOutOperateText(String.format(NumberUtil.isNullOrZero(amount) ? "" : "联系用户超时%s分钟，处罚：%s元", time <= minTime ? 1 : time, MoneyUtil.parseToYuanStr(amount)));
            }
            return;
        }
        // 联系用户后上门超时时间
        final boolean visit = Objects.equals(orderWork.getStatus(), OrderStatusConsts.WORK_STATUS_TAKE) && Objects.nonNull(orderWork.getDutyTime()) && Objects.equals(orderWork.getResultStatus(), OrderStatusConsts.WORK_RESULT_DOING);
        if (visit) {
            final Integer contactTineOutDate = Optional.ofNullable(DubboResponseUtils.resultToNull(() -> orderTimeoutWarningListRemoteService.getTimeoutWarningConfig(ConfigNodeType.VISIT, ConfigType.TIMEOUT, BizTypeEnum.codeOf(orderWork.getBizType()), ConfigName.AFTER_DUTY_TIME))).orElse(0);
            final Date from = Date.from(orderWork.getDutyTime().toInstant().plus(contactTineOutDate, ChronoUnit.MINUTES));
            this.calculateTimeDiff(now,from);
            programme.setTimeOutDate(from.getTime());
            if (now.after(from)) {
                final long time = (now.getTime() - from.getTime()) / 1000 / 60;
                dio.setType(PerfConfConstant.INDEX_SHARE_VISIT);
                Integer amount = Math.abs(this.getBonusConfigFiveDRO(dio, false));
                programme.setTimeOutOperateText(String.format(NumberUtil.isNullOrZero(amount) ? "" : "已上门超时%s分钟，处罚：%s元", time <= minTime ? 1 : time, MoneyUtil.parseToYuanStr(amount)));
            }
            return;
        }
    }

    /**
     * 超时时间不满1分钟的时候按1分钟算
     * @param startDate 开始时间
     * @param endDate 超时时间
     */
    private void calculateTimeDiff(Date startDate, Date endDate) {
        final long time = (startDate.getTime() - endDate.getTime()) / 1000 / 60;
        if (time <= 1) {
            Date parse = DateUtil.parse(DateUtil.toString(endDate, DateUtil.FORMAT_DATETIME + ":00"));
            endDate = DateUtil.addMinute(parse, 1);
        }
    }

    private Integer getBonusConfigFiveDRO(ConfEngineerBonusDIO dio, Boolean type) {
        final BonusConfigFiveDRO bonusConfigFiveDRO = DubboResponseUtils.resultToNull(() -> confEngineerFiveListRemoteService.getBonusByQuery(dio));
        if (Objects.isNull(bonusConfigFiveDRO)) {
            return 0;
        }
        final BigDecimal amount = type ? bonusConfigFiveDRO.getBonus() : bonusConfigFiveDRO.getFine();
        return amount.intValue();
    }

    @Override
    public WorkProgrammeDTO getProgramme(WorkDetailDTO dto) throws OmsBaseException {
        WorkProgrammeDTO programme = new WorkProgrammeDTO();
        if (Objects.isNull(dto)) {
            return programme;
        }

        // 处理多次上门操作名称
        if (NumberUtil.isNotNullOrZero(dto.getMultipleVisitStatus())) {
            /*if (Objects.equals(dto.getMultipleVisitStatus(), OrderVisitStatusConsts.ORDER_VISIT_STATUS_APPLY)
                    && Objects.equals(dto.getMultiplePayStatus(), PayConsts.PAY_STATUS_DONE)) {
                programme.setOperateStr("出发");
                programme.setProgrammeStatus("已提交");
                programme.setProgrammeStr("");
                programme.setOperateTextStatus(AppConsts.OPERATE_TEXT_TYPE_VISIT_DEPART);
                programme.setOperateText(AppConsts.getOperateText(AppConsts.OPERATE_TEXT_TYPE_VISIT_DEPART));
                return programme;
            } else */
            if ((Objects.equals(dto.getMultipleVisitStatus(), OrderVisitStatusConsts.ORDER_VISIT_STATUS_APPLY)
                    && Objects.equals(dto.getMultiplePayStatus(), PayConsts.PAY_STATUS_DONE))
                    || Objects.equals(dto.getMultipleVisitStatus(), OrderVisitStatusConsts.ORDER_VISIT_STATUS_SET_OUT)) {
                programme.setOperateStr("上门");
                programme.setProgrammeStatus("已领单");
                programme.setProgrammeStr("");
                programme.setOperateTextStatus(AppConsts.OPERATE_TEXT_TYPE_VISIT_VISIT);
                programme.setOperateText(AppConsts.getOperateText(AppConsts.OPERATE_TEXT_TYPE_VISIT_VISIT));
                return programme;
            }
        }

        OrderWork orderWork = orderWorkService.findOrderWorkByKey(dto.getOrderId(), dto.getWorkId());
        if (Objects.isNull(orderWork)) {
            return programme;
        }

        // 获取工单操作状态
        Set<Long> tmpSet = Sets.newHashSet();
        tmpSet.add(dto.getWorkId());
        logger.debug("获取工单超时预警状态 入参：{}", JSON.toJSONString(tmpSet));
        com.zmn.common.dto2.ResponseDTO<Set<OrderTimeOutWarningCheckDRO>> checkResponseDTO = orderTimeoutWarningListRemoteService
                .checkOrderTimeoutWarning(tmpSet);
        logger.debug("获取工单超时预警状态 出参：{}", JSON.toJSONString(checkResponseDTO));
        programme.setOperateStatus(OPERATE_STATUS_NORMAL);
        if (checkResponseDTO.isSuccess() && CollectionUtil.isNotNullOrEmpty(checkResponseDTO.getData())) {
            checkResponseDTO.getData().stream().findFirst().ifPresent(checkDRO -> {
                if (checkDRO.getHasTimeout()) {
                    programme.setOperateStatus(OPERATE_STATUS_TIMEOUT);
                } else if (checkDRO.getHasWarning()) {
                    programme.setOperateStatus(OPERATE_STATUS_WARNING);
                }
            });
        }

        // 直营 or 非直营 ResponseDTO<Integer> engineerByEngineerIdRsp =
        logger.debug("getProgramme#getCertificatePassResult 入参 [{}]",orderWork.getMasterId());
        ResponseDTO<Boolean> engineerByEngineerIdRsp = engineerCertificateListRemoteService.getCertificatePassResult(orderWork.getMasterId());
        logger.debug("getProgramme#getCertificatePassResult 出参 [{}]",JSON.toJSONString(engineerByEngineerIdRsp));
        Boolean agent = Boolean.FALSE;
        if(engineerByEngineerIdRsp.isSuccess()){
            agent = engineerByEngineerIdRsp.getData();
        }


        Boolean existsTag = orderTagBService.existsCategoryTagByCategoryId(orderWork.getOrderId(), orderWork.getWorkId(), OrderTagConsts.TAG_CATEGORY_ID_EXCLUDE_PERFORMANCE);
        if (agent &&
                (Objects.equals(orderWork.getPlatWork(), GlobalConsts.PLAT_MARK_ZMN) || Objects.equals(orderWork.getPlatWork(), GlobalConsts.PLAT_MARK_CNHB))
                && !existsTag) {
            // 处理进程奖励信息
            logger.debug("获取绩效配置入参：platWork：{}, manageCompanyId：{}， bizType：{}", orderWork.getPlatWork(), orderWork.getManageCompanyId(), orderWork.getBizType());
            ResponseDTO<ConfBonusFiveDRO> responseDTO = confEngineerFiveListRemoteService.getBonusOnlyPlusById(orderWork.getPlatWork(), orderWork.getManageCompanyId(), orderWork.getBizType());
            logger.debug("获取绩效配置出参：{}", JSON.toJSONString(responseDTO));

            programme.setProgrammeStr(this.getWorkProgrammeInfo(orderWork, responseDTO.getData(), programme.getOperateStatus()));
        } else {
            programme.setProgrammeStr("");
        }

        // 处理状态信息
        programme.setProgrammeStatus(this.getProgrammeStatus(orderWork));

        // 处理操作信息
        programme.setOperateStr(this.getOperateStr(orderWork));
        // 判断计划行程前后
        List<String> operateStrList = Arrays.asList("出发", "上门", "完成服务");
        final Integer planStroke = operateStrList.contains(programme.getOperateStr()) ? PlanStrokeConsts.PLAN_STROKE_AFTER : PlanStrokeConsts.PLAN_STROKE_BEFORE;
        programme.setPlanStroke(planStroke);
        // 返修日程
        if (Objects.equals(programme.getOperateStr(), "完成服务")
                && Objects.equals(orderWork.getType(), OrderConsts.ORDER_TYPE_REWORK)) {
            programme.setProgrammeStr("免费返修");
        }

        this.getDistributeText(programme);
        Integer operateTextStatus = this.getOperateTextStatus(orderWork);
        programme.setOperateTextStatus(operateTextStatus);
        programme.setOperateText(AppConsts.getOperateText(operateTextStatus));
        this.getTimeOutDate(orderWork, programme);

        return programme;
    }


    private String getWorkProgrammeInfo(OrderWork orderWork, ConfBonusFiveDRO confDRO, Integer status) throws OmsBaseException {
        logger.debug("工单[{}]状态：{}", orderWork.getWorkId(), status);

        if (Objects.isNull(confDRO)) {
            return "";
        }

        // 检查工单是否有剔除工程师绩效标签


        // 判断工单当前在APP显示的状态
        OrderTimeoutTypeEnum timeoutTypeEnum = getTimeOutEnum(orderWork);
        logger.debug("工单[{}]当前超时状态：{}", orderWork.getWorkId(), timeoutTypeEnum.getDesc());

        if ((Objects.equals(orderWork.getPlatWork(), GlobalConsts.PLAT_MARK_ZMN) || Objects.equals(orderWork.getPlatWork(), GlobalConsts.PLAT_MARK_CNHB)) && !ZMN_CNHB_SHOW_LIST.contains(timeoutTypeEnum)) {
            return "";
        }
        if (Objects.equals(orderWork.getPlatWork(), GlobalConsts.PLAT_MARK_YEYX) && !YEYX_SHOW_LIST.contains(timeoutTypeEnum)) {
            return "";
        }

        Date timeOutDate = null; // 超时时间
        Date advanceTimeOutDate = null; // 提前上门超时时间 非必须
        if (!Objects.equals(status, OPERATE_STATUS_TIMEOUT)) {
            if (TIMEOUT_LIST.contains(timeoutTypeEnum)) {
                ResponseDTO<Date> dateResponseDTO = null;
                // 获取对应预警的超时时间
                logger.debug("获取超时时间入参：工单号：{}, 超时类型：{}", orderWork.getOrderId(), timeoutTypeEnum.getDesc());
                dateResponseDTO = orderTimeoutWarningListRemoteService.getTimeoutTimeByOrderId(orderWork.getOrderId(), timeoutTypeEnum);
                logger.debug("获取超时时间出参：：工单号：{} 返回：{}", orderWork.getOrderId(), JSON.toJSONString(dateResponseDTO));

                if (!dateResponseDTO.isSuccess()) {
                    logger.info("获取工单超时时间错误：{}", JSON.toJSONString(dateResponseDTO));
                    return "";
                }
                if (Objects.nonNull(dateResponseDTO.getData())) {
                    timeOutDate = dateResponseDTO.getData();
                }

                // 处理提前上门超时时间
                if (Objects.equals(timeoutTypeEnum, OrderTimeoutTypeEnum.VISIT)) {
                    logger.debug("获取提前超时时间配置入参：工单号：{}, 业务类型：{}", orderWork.getOrderId(), orderWork.getBizType());
                    ResponseDTO<Integer> advanceTimeOutConfigResponse = orderTimeoutWarningListRemoteService.getTimeoutWarningConfig(ConfigNodeType.VISIT, ConfigType.TIMEOUT, BizTypeEnum.codeOf(orderWork.getBizType()), ConfigName.BEFORE_DUTY_TIME);
                    logger.debug("获取提前超时时间配置出参：：工单号：{} 返回：{}", orderWork.getOrderId(), JSON.toJSONString(advanceTimeOutConfigResponse));
                    if (!advanceTimeOutConfigResponse.isSuccess()) {
                        logger.info("获取工单超时时间错误：{}", JSON.toJSONString(advanceTimeOutConfigResponse));
                        return "";
                    }
                    if (Objects.nonNull(advanceTimeOutConfigResponse.getData())) {
                        advanceTimeOutDate = Date.from(orderWork.getDutyTime().toInstant().minus(advanceTimeOutConfigResponse.getData(), ChronoUnit.MINUTES));
                    }
                }
            }
        }
        String result = "";

        // 拼装信息语句 true 已过时 false 未过时
        switch (timeoutTypeEnum) {
            case TAKE:
                if (Objects.equals(OPERATE_STATUS_TIMEOUT, status)) {
                    result = String.format(TIP_TIMEOUT_TEMPLATE, "领单");
                }
                break;
            case CONTACT:
                // 如果挂起 不显示
                if (Objects.isNull(orderWork.getSuspendTime())) {
                    if (Objects.isNull(orderWork.getContactTime())) {
                        result = processReturnString(
                                performanceUtilService.conversionPerformanceAmount(orderWork.getOrderId(),confDRO.getOnTimeContact(),confDRO.getOnTimeContactValType()),
                                advanceTimeOutDate,
                                timeOutDate,
                                "联系用户",
                                status,
                                orderWork);
                    }
                }
                break;
            case DUTY:
                // 如果挂起 不显示
                if (Objects.isNull(orderWork.getSuspendTime())) {
                    if (Objects.isNull(orderWork.getDutyTime())) {
                        result = processReturnString(
                                performanceUtilService.conversionPerformanceAmount(orderWork.getOrderId(),confDRO.getOnTimeDuty(),confDRO.getOnTimeDutyValType()),
                                advanceTimeOutDate,
                                timeOutDate,
                                "完善时间",
                                status,
                                orderWork);
                    }
                }
                break;
            case VISIT:
                result = processReturnString(
                        performanceUtilService.conversionPerformanceAmount(orderWork.getOrderId(),confDRO.getOnTimeVisit(),confDRO.getOnTimeVisitValType()),
                        advanceTimeOutDate,
                        timeOutDate,
                        "上门",
                        status,
                        orderWork);
                if (StringUtils.isBlank(result) && Objects.equals(orderWork.getIsLeave(), GlobalConsts.NO)) {
                    result = "告知用户已出发，可减少催单";
                }
                break;
            case COMPLETE:
                if (Objects.equals(orderWork.getType(), OrderConsts.ORDER_TYPE_REWORK)) {
                    return "";
                }
                Integer amount = 0;
                // 无及时完成指标
//                if (NumberUtil.isNotNullOrZero(confDRO.getOnTimePay()) && NumberUtil.isNotNullOrZero(confDRO.getCompleteInDay())) {
//                    amount = confDRO.getOnTimePay() + confDRO.getCompleteInDay();
//                    String tipName = null;
//                    if (Objects.equals(status, OPERATE_STATUS_NORMAL)) {
//                        tipName = "现场支付";
//                    } else {
//                        tipName = "完成";
//                    }
//                    result = processReturnString(amount, timeOutDate, tipName, status);
//                } else
                if (NumberUtil.isNotNullOrZero(confDRO.getOnTimePay()) && (Objects.equals(GlobalConsts.PLAT_MARK_CNHB, orderWork.getPlatWork()) || Objects.equals(GlobalConsts.PLAT_MARK_ZMN, orderWork.getPlatWork()))) {
                    amount = performanceUtilService.conversionPerformanceAmount(orderWork.getOrderId(), confDRO.getOnTimePay(), confDRO.getOnTimePayValType());
                    if (NumberUtil.isNotNullOrZero(amount)) {
                        result = String.format("现场支付，奖励%s元", MoneyUtil.parseToYuanStr(amount));
                    }
                } else if (NumberUtil.isNotNullOrZero(confDRO.getCompleteInDay()) && Objects.equals(GlobalConsts.PLAT_MARK_YEYX, orderWork.getPlatWork()) && Objects.equals(com.zmn.consts.GlobalConsts.BIZ_TYPE_F, orderWork.getBizType())) {
                    amount = performanceUtilService.conversionPerformanceAmount(orderWork.getOrderId(), confDRO.getCompleteInDay(), confDRO.getCompleteInDayValType());
                    timeOutDate = get24CompleteTimeOutTime(orderWork.getWorkId());
                    if (NumberUtil.isNotNullOrZero(amount)) {
                        result = processReturnString(amount, advanceTimeOutDate, timeOutDate, "完成", status, orderWork);
                    }
                }
                break;
            default:
                result = "";
        }
        return result;
    }

    private String processReturnString(Integer amount,
                                       Date advanceTimeOutDate,
                                       Date timeOutDate,
                                       String tipName,
                                       Integer status,
                                       OrderWork orderWork) {
        if (Objects.isNull(status)) {
            return "";
        }
        // 完善时间奖励 目前暂不支持
        // 新单
        if (Objects.equals(orderWork.getType(), OrderConsts.ORDER_TYPE_NEW)) {
            switch (status) {
                case OPERATE_STATUS_NORMAL:
                case OPERATE_STATUS_WARNING:
                    if (Objects.nonNull(timeOutDate) && NumberUtil.isNotNullOrZero(amount)) {
                        StringBuilder dateStr = new StringBuilder();
                        if (Objects.nonNull(advanceTimeOutDate)) {
                            dateStr.append(getDateStr(advanceTimeOutDate)).append("~");
                        }
                        dateStr.append(appendDateUnit(getDateStr(timeOutDate)));
                        if (Objects.nonNull(advanceTimeOutDate)) {
                            return String.format(TIP_NORMAL_SECTION_TEMPLATE, dateStr, tipName, MoneyUtil.parseToYuanStr(amount));
                        }
                        return String.format(TIP_NORMAL_TEMPLATE, dateStr, tipName, MoneyUtil.parseToYuanStr(amount));
                    } else if (Objects.nonNull(timeOutDate) && NumberUtil.isNullOrZero(amount) && Objects.equals(status, OPERATE_STATUS_WARNING)){
                        return String.format(TIP_WARNING_TEMPLATE, appendDateUnit(getDateStr(timeOutDate)), tipName);
                    } else {
                        return "";
                    }
//                return String.format(TIP_WARNING_TEMPLATE, DateUtil.toString(timeOutDate, DATE_TEMPLATE), tipName);
                case OPERATE_STATUS_TIMEOUT:
                    return String.format(TIP_TIMEOUT_TEMPLATE, tipName);
                default:
                    return "";
            }
        } else if (Objects.equals(orderWork.getType(), OrderConsts.ORDER_TYPE_REWORK)) {
            switch (status) {
                case OPERATE_STATUS_WARNING:
                    if (Objects.nonNull(timeOutDate)) {
                        return String.format(TIP_WARNING_TEMPLATE, appendDateUnit(getDateStr(timeOutDate)), tipName);
                    } else {
                        return "";
                    }
//                return String.format(TIP_WARNING_TEMPLATE, DateUtil.toString(timeOutDate, DATE_TEMPLATE), tipName);
                case OPERATE_STATUS_TIMEOUT:
                    return String.format(TIP_TIMEOUT_TEMPLATE, tipName);
                default:
                    return "";
            }
        } else {
            return "";
        }
    }

    private OrderTimeoutTypeEnum getTimeOutEnum(OrderWork orderWork) {
        if (Objects.equals(orderWork.getStatus(), OrderStatusConsts.WORK_STATUS_DISTRIBUTE) && Objects.equals(orderWork.getResultStatus(), OrderStatusConsts.WORK_RESULT_DOING)) {
            // 待领单（已派单-进行中）
            return OrderTimeoutTypeEnum.TAKE;
        } else if (Objects.equals(orderWork.getStatus(), OrderStatusConsts.WORK_STATUS_TAKE) && (Objects.isNull(orderWork.getDutyTime()) || Objects.isNull(orderWork.getContactTime())) && Objects.isNull(orderWork.getCompleteTime()) && Objects.equals(orderWork.getResultStatus(), OrderStatusConsts.WORK_RESULT_DOING)) {
            // 待预约（状态结果：未取消/未完成-进行中” & 预约时间为：空）
            if (Objects.isNull(orderWork.getContactTime())) {
                return OrderTimeoutTypeEnum.CONTACT;
            } else {
                return OrderTimeoutTypeEnum.DUTY;
            }
        } else if (Objects.equals(orderWork.getStatus(), OrderStatusConsts.WORK_STATUS_TAKE) && Objects.equals(orderWork.getResultStatus(), OrderStatusConsts.WORK_RESULT_DOING)) {
            // 待上门
            return OrderTimeoutTypeEnum.VISIT;
        } else {
            // 完成
            return OrderTimeoutTypeEnum.COMPLETE;
        }
    }

    @Override
    public String getOperateStr(OrderWork orderWork) {
        if (Objects.equals(orderWork.getStatus(), OrderStatusConsts.WORK_STATUS_DISTRIBUTE) && Objects.equals(orderWork.getResultStatus(), OrderStatusConsts.WORK_RESULT_DOING)) {
            // 待领单（已派单-进行中）
            return "领单";
        } else if (Objects.equals(orderWork.getStatus(), OrderStatusConsts.WORK_STATUS_TAKE) && (Objects.isNull(orderWork.getDutyTime()) || Objects.isNull(orderWork.getContactTime())) && Objects.isNull(orderWork.getCompleteTime()) && Objects.equals(orderWork.getResultStatus(), OrderStatusConsts.WORK_RESULT_DOING)) {
            // 待预约（状态结果：未取消/未完成-进行中” & 预约时间为：空）
            if (Objects.isNull(orderWork.getContactTime())) {
                return "联系用户";
            } else {
                return "预约时间";
            }
        } else if (Objects.equals(orderWork.getStatus(), OrderStatusConsts.WORK_STATUS_TAKE) && Objects.equals(orderWork.getResultStatus(), OrderStatusConsts.WORK_RESULT_DOING)) {
            if (Objects.equals(orderWork.getIsLeave(), GlobalConsts.NO)) {
                StockWhiteDTO stockWhiteDTO = StockWhiteDTO.builder()
                        .masterId(orderWork.getMasterId())
                        .workCityId(orderWork.getCityId())
                        .build();
                boolean whiteByAllConditions = orderStockBService.isWhiteByAllConditions(stockWhiteDTO);
                if (whiteByAllConditions) {
                    CheckLockStockDTO checkLockStockDTO = orderStockBService.getCheckLockStockDTO(orderWork);
                    boolean isLockStock = orderStockBService.checkIsLockStock(checkLockStockDTO);
                    if (isLockStock) {
                        ResponseDTO<Boolean> checkExitOrderRemote = stockListRemoteService.checkExitOrder(orderWork.getMasterId(), String.valueOf(orderWork.getOrderId()));
                        if (Objects.equals(checkExitOrderRemote.getData(), false)) {
                            return "计划行程";
                        }
                    }
                }
                return "出发";
            } else {
                return "上门";
            }
        } else {
            // 完成
            return "完成服务";
        }
    }


    @Override
    public Integer getOperateTextStatus(OrderWork orderWork) {
        if (Objects.equals(orderWork.getStatus(), OrderStatusConsts.WORK_STATUS_DISTRIBUTE) && Objects.equals(orderWork.getResultStatus(), OrderStatusConsts.WORK_RESULT_DOING)) {
            // 待领单（已派单-进行中）
            return AppConsts.OPERATE_TEXT_TYPE_TAKE;
        } else if (Objects.equals(orderWork.getStatus(), OrderStatusConsts.WORK_STATUS_TAKE)
                && (Objects.isNull(orderWork.getDutyTime()) || Objects.isNull(orderWork.getContactTime()))
                && Objects.isNull(orderWork.getCompleteTime())
                && Objects.equals(orderWork.getResultStatus(), OrderStatusConsts.WORK_RESULT_DOING)) {
            // 试点工程师，需要占用库存。没有占用过库存 或者 工程师没有改约过时间
            StockWhiteDTO stockWhiteDTO = StockWhiteDTO.builder()
                    .masterId(orderWork.getMasterId())
                    .workCityId(orderWork.getCityId())
                    .build();
            boolean whiteByAllConditions = orderStockBService.isWhiteByAllConditions(stockWhiteDTO);
            if (whiteByAllConditions) {
                CheckLockStockDTO checkLockStockDTO = orderStockBService.getCheckLockStockDTO(orderWork);
                boolean isLockStock = orderStockBService.checkIsLockStock(checkLockStockDTO);
                if (isLockStock) {
                    ResponseDTO<Boolean> checkExitOrderRemote = stockListRemoteService.checkExitOrder(orderWork.getMasterId(), String.valueOf(orderWork.getOrderId()));
                    if (Objects.equals(checkExitOrderRemote.getData(), false)) {
                        return AppConsts.OPERATE_TEXT_TYPE_PLAN_TRIP;
                    }

                    MasterWorking masterWorking = masterWorkingService.findMasterWorkingByWorkId(orderWork.getWorkId());
                    if (Objects.equals(masterWorking.getWaitScheduling(), GlobalConsts.NO)) {
                        return AppConsts.OPERATE_TEXT_TYPE_PLAN_TRIP;
                    }
                }
            }
            // 待预约（状态结果：未取消/未完成-进行中” & 预约时间为：空）
            if (Objects.isNull(orderWork.getContactTime())) {
                return AppConsts.OPERATE_TEXT_TYPE_CONTACT;
            } else {
                return AppConsts.OPERATE_TEXT_TYPE_DUTY_TIME;
            }
        } else if (Objects.equals(orderWork.getStatus(), OrderStatusConsts.WORK_STATUS_TAKE) && Objects.equals(orderWork.getResultStatus(), OrderStatusConsts.WORK_RESULT_DOING)) {
            StockWhiteDTO stockWhiteDTO = StockWhiteDTO.builder()
                    .masterId(orderWork.getMasterId())
                    .workCityId(orderWork.getCityId())
                    .build();
            boolean whiteByAllConditions = orderStockBService.isWhiteByAllConditions(stockWhiteDTO);
            if (whiteByAllConditions) {
                CheckLockStockDTO checkLockStockDTO = orderStockBService.getCheckLockStockDTO(orderWork);
                boolean isLockStock = orderStockBService.checkIsLockStock(checkLockStockDTO);
                if (isLockStock) {
                    ResponseDTO<Boolean> checkExitOrderRemote = stockListRemoteService.checkExitOrder(orderWork.getMasterId(), String.valueOf(orderWork.getOrderId()));
                    if (Objects.equals(checkExitOrderRemote.getData(), false)) {
                        return AppConsts.OPERATE_TEXT_TYPE_PLAN_TRIP;
                    }

                    MasterWorking masterWorking = masterWorkingService.findMasterWorkingByWorkId(orderWork.getWorkId());
                    if (Objects.equals(masterWorking.getWaitScheduling(), GlobalConsts.NO)) {
                        return AppConsts.OPERATE_TEXT_TYPE_PLAN_TRIP;
                    }
                }
            }
            return AppConsts.OPERATE_TEXT_TYPE_VISIT;
        } else {
            // 完成
            return AppConsts.OPERATE_TEXT_TYPE_COMPLETE;
        }
    }

    @Override
    public String getProgrammeStatus(OrderWork orderWork) {
        if (Objects.equals(orderWork.getStatus(), OrderStatusConsts.WORK_STATUS_DISTRIBUTE) && Objects.equals(orderWork.getResultStatus(), OrderStatusConsts.WORK_RESULT_DOING)) {
            // 待领单（已派单-进行中）
            return "待领单";
        } else if (Objects.equals(orderWork.getStatus(), OrderStatusConsts.WORK_STATUS_TAKE) && Objects.isNull(orderWork.getDutyTime()) && Objects.isNull(orderWork.getCompleteTime()) && Objects.equals(orderWork.getResultStatus(), OrderStatusConsts.WORK_RESULT_DOING)) {
            return "待预约";
        } else if (Objects.equals(orderWork.getStatus(), OrderStatusConsts.WORK_STATUS_TAKE) && Objects.isNull(orderWork.getContactTime()) && Objects.isNull(orderWork.getCompleteTime()) && Objects.equals(orderWork.getResultStatus(), OrderStatusConsts.WORK_RESULT_DOING)) {
            return "待联系";
        } else if (Objects.equals(orderWork.getStatus(), OrderStatusConsts.WORK_STATUS_TAKE) && Objects.equals(orderWork.getResultStatus(), OrderStatusConsts.WORK_RESULT_DOING)) {
            return "待上门";
        } else {
            // 完成
            return "已上门";
        }
    }

    @Data
    @AllArgsConstructor
    static class DuplicateDTO {
        private Integer platWork;
        private Integer manageCompanyId;
        private Integer bizType;

        @Override
        public int hashCode() {
            String hash = "" + platWork + manageCompanyId + bizType;
            return Integer.valueOf(hash);
        }

        @Override
        public boolean equals(Object obj) {
            DuplicateDTO dto = (DuplicateDTO) obj;
            return platWork.equals(dto.platWork) && manageCompanyId.equals(dto.getManageCompanyId()) && bizType.equals(dto.getBizType());
        }
    }

    @Override
    public void sendOperateInfo(Long orderId, Integer operateId) {
        OrderWork orderWork = orderWorkService.findOrderWorkByKey(orderId, orderId);

        MsgDTO msgDTO = this.getMsgDTO(orderId, operateId);
        if (NumberUtil.isNullOrZero(msgDTO.getMsgId())) {
            return;
        }

        logger.info("{} 操作结果：{}", orderId, msgDTO.getMsg());
        Map<String, Object> params = Maps.newHashMap();
        params.put("order_id", String.valueOf(orderWork.getOrderId()));
        params.put("work_id", String.valueOf(orderWork.getOrderId()));
        params.put("biz_type", String.valueOf(orderWork.getBizType()));
        params.put("master_id", String.valueOf(orderWork.getMasterId()));
        messageSendAppService.pushAppMessageInfo(msgDTO.getMsgId(), Json.toString(params), orderWork);
    }

    @Override
    public String getOperateInfo(Long orderId, Integer operateId) {
        return this.getMsgDTO(orderId, operateId).getMsg();
    }

    public MsgDTO getMsgDTO(Long orderId, Integer operateId) {
        Integer confEngineerBonusType = null;
        OrderTimeoutTypeEnum timeoutTypeEnum;
        switch (operateId) {
            case AppConsts.OPERATE_TYPE_TAKE:
                timeoutTypeEnum = OrderTimeoutTypeEnum.TAKE;
                confEngineerBonusType = PerfConfConstant.INDEX_SHARE_TAKE;
                break;
            case AppConsts.OPERATE_TYPE_CONTACT:
                timeoutTypeEnum = OrderTimeoutTypeEnum.CONTACT;
                confEngineerBonusType = PerfConfConstant.INDEX_SHARE_CONTACT;
                break;
            case AppConsts.OPERATE_TYPE_VISIT:
                timeoutTypeEnum = OrderTimeoutTypeEnum.VISIT;
                confEngineerBonusType = PerfConfConstant.INDEX_SHARE_VISIT;
                break;
            case AppConsts.OPERATE_TYPE_COMPLETE:
                timeoutTypeEnum = OrderTimeoutTypeEnum.COMPLETE;
                break;
            default:
                timeoutTypeEnum = null;
        }

        Integer msgId = 0;
        String operateMsg = "";
        if (Objects.nonNull(timeoutTypeEnum)) {
            // 获取超时信息
            logger.debug("获取工单超时信息：入参：{} {}", orderId, timeoutTypeEnum.getCode());
            ResponseDTO<Boolean> responseDTO = orderTimeoutWarningListRemoteService.checkOrderTimeoutStatus(orderId, timeoutTypeEnum);
            logger.debug("获取工单超时信息：出参：{} {}", JSON.toJSONString(responseDTO));
            if (responseDTO.isSuccess()) {
                if (BooleanUtils.isFalse(responseDTO.getData())) {
                    // 准时领单，上门，联系获取正激励
                    List<OrderWork> orderWorks = orderWorkService.listOrderWorkByOrderIdList(Arrays.asList(orderId));
                    if (CollectionUtil.isNotNullOrEmpty(orderWorks) && Objects.nonNull(confEngineerBonusType)) {
                        OrderWork orderWork = orderWorks.get(0);
                        ConfEngineerBonusDIO dio = new ConfEngineerBonusDIO();
                        dio.setWorkId(orderWork.getWorkId());
                        dio.setCompanyId(orderWork.getManageCompanyId());
                        dio.setPlat(orderWork.getPlat());
                        dio.setBizType(orderWork.getBizType());
                        dio.setType(confEngineerBonusType);
                        // 根据操作类型返回不同的提示语
                        Integer amount = this.getBonusConfigFiveDRO(dio, true);
                        operateMsg = String.format(OPERATE_RESULT_SUCCESS_TEMPLATE_AMOUNT, AppConsts.getOperateName(operateId), MoneyUtil.parseToYuanStr(amount));
                        msgId = AppConsts.getOnTimeMsgId(operateId);
                    } else {
                        operateMsg = String.format(OPERATE_RESULT_SUCCESS_TEMPLATE, AppConsts.getOperateName(operateId));
                        msgId = AppConsts.getOnTimeMsgId(operateId);
                    }
                } else {
                    operateMsg = String.format(OPERATE_RESULT_FAIL_TEMPLATE, AppConsts.getOperateName(operateId));
                    msgId = AppConsts.getOutTimeMsgId(operateId);
                }
            }
        }

        MsgDTO msgDTO = new MsgDTO(msgId, operateMsg);

        return msgDTO;
    }

    @Data
    @AllArgsConstructor
    class MsgDTO {
        private Integer msgId;

        private String msg;
    }

    private Date get24CompleteTimeOutTime(Long workId) {
        OrderChangeRecord record = orderChangeRecordService.getChangeRecordByOrderId(workId);
        if (Objects.isNull(record) || Objects.isNull(record.getLastDutyTime())) {
            return null;
        }
        return Date.from(record.getLastDutyTime().toInstant().plus(24, ChronoUnit.HOURS));
    }

    private String getDateStr(Date date) {
        Date curTime = new Date();
        String dateStr = DateUtil.toString(date, DateUtil.FORMAT_DATE);
        String curDateStr = DateUtil.toString(curTime, DateUtil.FORMAT_DATE);

        String resultStr = "";

        if (dateStr.equals(curDateStr)) {
            resultStr = DateUtil.toString(date, DATE_TEMPLATE);
        } else if (dateStr.equals(DateUtil.toString(DateUtil.getBaseDefer(curTime, 1), DateUtil.FORMAT_DATE))) {
            resultStr = "明天" + DateUtil.toString(date, DATE_TEMPLATE);
        } else {
            resultStr = DateUtil.toString(date, "M月d日 " + DATE_TEMPLATE);
        }
        return resultStr;
    }

    private String appendDateUnit(String date) {
        if (date.endsWith("00")) {
            return date + "时";
        } else {
            return date + "分";
        }
    }
}
